package org.jvending.provisioning.stocking.handler;

import org.hibernate.Hibernate;
import org.jvending.provisioning.config.MimeTypeRepository;
import org.jvending.provisioning.model.clientbundle.ContentFile;
import org.jvending.provisioning.stocking.StockingException;
import org.jvending.provisioning.stocking.par.DescriptorFileType;
import org.jvending.registry.RepositoryRegistry;
import org.kxml2.io.KXmlParser;
import org.xmlpull.v1.XmlPullParserException;

import java.io.ByteArrayInputStream;
import java.io.IOException;
import java.sql.Blob;
import java.util.ArrayList;
import java.util.List;
import java.util.Map;
import java.util.logging.Logger;

public class JnlpHandler implements DescriptorHandler {

    private static Logger logger = Logger.getLogger("JnlpHandler");

    /**
     * RepositoryRegisty instance
     */
    private RepositoryRegistry repositoryRegistry;

    public void setRepositoryRegistry(RepositoryRegistry repositoryRegistry) {
        this.repositoryRegistry = repositoryRegistry;
    }

    /**
     * @param descriptorFileType for a JNLP
     * @param contentMap
     * @return List containing <code>ContentFile</code>s
     * @throws org.jvending.provisioning.stocking.StockingException
     *
     */
    public List<ContentFile> getContentFiles(DescriptorFileType descriptorFileType, Map contentMap) throws StockingException {
        List<ContentFile> contents = new ArrayList<ContentFile>();

        if (descriptorFileType == null || contentMap == null) {
            logger.info("JV-1800-009: One of the required parameters is missing");
            throw new StockingException("JV-1800-009: One of the required parameters is missing");
        }

        if (repositoryRegistry == null) {
            logger.severe("JV-1800-010: RepositoryRegistry not set.");
            throw new StockingException("JV-1800-010: RepositoryRegistry not set.");
        }

        logger.finest("JV-1800-001: Starting JNLP HANDLER");

        String uri = descriptorFileType.getValue();

        if (uri == null || isRemoteUri(uri.trim())) {
            logger.finest("JV-1800-002: Remote or null URI. Not processing content: URI = " + uri);
            return contents;
        }

        uri = uri.trim();

        String mimeType = descriptorFileType.getMimeType();
        MimeTypeRepository mimeRepo = (MimeTypeRepository) repositoryRegistry.find("mimetype");
        if (mimeType == null) mimeType = mimeRepo.getMimeTypeFromUri(descriptorFileType.getValue());

        if (mimeType == null) {
            logger.info("JV-1800-003: Cannot determine the mime-type of this descriptor: URI = " + uri);
            return contents;
        }

        if (!mimeType.equals("application/x-java-jnlp-file")) {
            logger.info("JV-1800-004: Not JAD mime-type: URI = " + uri + ", mimeType = " + mimeType);
            return contents;
        }

        byte[] descriptorBytes = (byte[]) contentMap.get(uri);
        if (descriptorBytes == null) {
            logger.info("JV-1800-005: Cannot find local copy of this descriptor: URI = " + uri);
            return contents;
        }

        KXmlParser parser = new KXmlParser();
        try {
            parser.setInput(new ByteArrayInputStream(descriptorBytes), null);
        } catch (XmlPullParserException e) {
            throw new StockingException();
        }

        try {

            int eventType = parser.getEventType();
            do {
                if (eventType == parser.START_TAG) {
                    String href = parser.getAttributeValue(null, "href");
                    if (href != null && !isRemoteUri(href)) {
                        byte[] content = (byte[]) contentMap.get(href);
                        //byte  null
                        Blob contentBlob = null;
                        ByteArrayInputStream is = new ByteArrayInputStream(content);
                        contentBlob = Hibernate.createBlob(is, content.length);
                        ContentFile contentFile = new ContentFile();
                        contentFile.setContent(contentBlob);
                        contentFile.setFileUri(href);
                        contentFile.setMimeType("application/x-java-jnlp-file");
                        contentFile.setBytes(content);
                        contents.add(contentFile);
                    }
                }
                eventType = parser.next();
            } while (eventType != parser.END_DOCUMENT);
        } catch (IOException e) {
            throw new StockingException();
        } catch (XmlPullParserException e) {
            e.printStackTrace();
            throw new StockingException();
        }
        return contents;
    }

    private boolean isRemoteUri(String uri) {
        return (uri != null && (uri.startsWith("http://") || uri.startsWith("ftp://") || uri.startsWith("https://")));
    }
}
